﻿using Cysharp.Threading.Tasks;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;

/// <summary>
/// 资源缓存类，在需要使用的地方实例化调用
/// </summary>
public class AssetCache<TKey, TAsset> where TAsset : Object
{
    private Dictionary<TKey, TAsset> m_Cache = new Dictionary<TKey, TAsset>();
    private HashSet<TKey> m_LoadingKeys = new HashSet<TKey>();

    /// <summary>
    /// 异步加载
    /// </summary>
    public async UniTask<TAsset> LoadAsync(TKey key)
    {
        // 已缓存，则直接取出
        if (m_Cache.TryGetValue(key, out var asset)) return asset;
        // 正在加载，则等待其加载完毕，再直接从缓存中读取
        if (m_LoadingKeys.Contains(key))
        {
            await UniTask.WaitUntil(() => !m_LoadingKeys.Contains(key));
            return m_Cache[key];
        }
        // 未缓存，则加入缓存列表，等待缓存结束后取出
        m_LoadingKeys.Add(key);
        asset = await Addressables.LoadAssetAsync<TAsset>(key).Task;
        if (asset == null) return null;
        m_Cache[key] = asset;
        m_LoadingKeys.Remove(key);
        return asset;
    }

    /// <summary>
    /// 同步加载
    /// </summary>
    public TAsset Load(TKey key)
    {
        // 已缓存，则直接取出
        if (m_Cache.TryGetValue(key, out var asset)) return asset;
        // 未缓存，则加入缓存列表，等待缓存结束后取出
        m_LoadingKeys.Add(key);
        asset = Addressables.LoadAssetAsync<TAsset>(key).WaitForCompletion();
        if (asset == null) return null;
        m_Cache[key] = asset;
        m_LoadingKeys.Remove(key);
        return asset;
    }

    ///// <summary>
    ///// 从缓存中同步加载
    ///// </summary>
    //public TAsset Load(TKey key)
    //{
    //    m_Cache.TryGetValue(key, out TAsset asset);
    //    return asset;
    //}

    public void Release()
    {
        foreach (var asset in m_Cache.Values)
        {
            Addressables.Release(asset);
        }
        m_Cache.Clear();
    }
}